#include "StdAfx.h"
#include "DummyHandler.h"
#include "ConfigManager.h"
//#include "Allocator.h"
//#include "PacketData.h"

extern DWORD g_ConnectionCount;
DummyHandler::DummyHandler()
{
	REGISTR_HANDLER(USER_CONNECT_REGISTER, DummyHandler::recv_connect_auth);
	REGISTR_HANDLER(CHAT_START_MESSAGE, DummyHandler::recv_chat_start);
	REGISTR_HANDLER(CHAT_MESSAGE, DummyHandler::recv_chat_message);
}

DummyHandler::~DummyHandler(void)
{
	this->close();
}

void DummyHandler::close()
{
	stream_.close();

}
ACE_HANDLE DummyHandler::handle() const
{
	return stream_.get_handle();
}

void DummyHandler::handle(ACE_HANDLE handle)
{
	stream_.set_handle(handle);
}

bool DummyHandler::connect() 
{
	return this->connected_;
}

int DummyHandler::open()
{
	char inetAddr[128]= {0};
	sprintf(inetAddr, "%s:%d", "127.0.0.1", 9000);

	ACE_INET_Addr remote_addr(inetAddr);

	this->proactor(ACE_Proactor::instance());

	ACE_SOCK_Connector connector;
	if(-1 == connector.connect(stream_, remote_addr))
	{
		LOG_ERROR(("connect"));
		return -1;
	}

	this->connected_ = true;
	
	if(-1 == writer_.open(*this))
	{
		LOG_ERROR(("writer.open()"));
		return -1;
	}

	if(-1 == reader_.open(*this))
	{
		LOG_ERROR(("reader_.open()"));
		return -1;
	}

	if(false == initiate_read_stream())
	{
		LOG_ERROR(("initiate_read_stream"));
		return -1;
	}
	
	return 0;
}

bool DummyHandler::initiate_read_stream()
{
	ACE_Message_Block* mb = AllocatorMgr->packet_block_alloc();
	if(mb)
	{
		if(0 == reader_.read(*mb, mb->size()))
		{
			return true;
		}
		else
		{
			LOG_ERROR(("reader_.read() fail"));
		}
	}
	else
	{
		LOG_ERROR(("MsgBlockAlloc() fail"));
	}

	return false;
}

void DummyHandler::make_name()
{
	this->user_name_.append("Player_");

	char temp[10] = {0};
	ACE_OS::itoa(this->user_index(), temp, 10);
	this->user_name_.append(temp);

	LOG_TRACE(("[sucess] make_name [%s]", 
		/*this->user_index_, */
		this->user_name_.c_str()));
}

///////////////////////////////////////////////////////////////////
// virtual function
///////////////////////////////////////////////////////////////////
void DummyHandler::handle_read_stream(const ACE_Asynch_Read_Stream::Result &result)
{
	ACE_Message_Block& mb = result.message_block();

	if((false == result.success()) || (0 == result.bytes_transferred()))
	{
		connected_ = false;
		AllocatorMgr->packet_block_free(&mb);
		LOG_ERROR(("%s disconnected(%d, %d)", 
							  user_name_.c_str(), 
							  result.success(), 
							  result.bytes_transferred()));
	}
	else
	{
		if(mb.length() >= sizeof(PK_Header))
		{
			if(0 == recv_packet_parsing(mb))
			//if(0 == ConfigMgr->recv_packet_parsing(*this, mb))
			{
				AllocatorMgr->packet_block_free(&mb);
				this->initiate_read_stream();
			}
			else
			{
				AllocatorMgr->packet_block_free(&mb);
				this->initiate_read_stream();
			}
		}
	}
}

void DummyHandler::handle_write_stream(const ACE_Asynch_Read_Stream::Result &result)
{
	ACE_Message_Block& mb = result.message_block();
	AllocatorMgr->packet_block_free(&mb);

	if(result.success())
	{
		initiate_read_stream();
	}
}

void DummyHandler::handle_time_out(const ACE_Time_Value& current_time, const void* act)
{        
	send_random_chat();
}


///////////////////////////////////////////////////////////////////
// Recv
///////////////////////////////////////////////////////////////////
int DummyHandler::recv_packet_parsing(ACE_Message_Block& mb)
{
	PK_Header* header = reinterpret_cast<PK_Header*>(mb.rd_ptr());
	PacketData recv_data(header->packet_code_);
	recv_data.resize(header->data_len_);

	std::memcpy((void*)recv_data.contents(), 
					  (char*)mb.rd_ptr() + sizeof(PK_Header), 
					  header->data_len_);

	ServiceRegister::const_iterator iter = svc_handler_.find(header->packet_code_);
	if(iter == svc_handler_.end())
	{
		LOG_ERROR(("unregister service code : [%d]", header->packet_code_));
		AllocatorMgr->packet_block_free(&mb);
		return -1;
	}

	SvcHandler<DummyHandler> f = iter->second;
	int ret = (this->*f.svc_handler_)(recv_data);
	if(0 != ret)
	{
		LOG_ERROR(("service handler error return : [%d]", header->packet_code_));
		return -1;
	}

	return 0;
}

int DummyHandler::recv_connect_auth(PacketData& recv_data)
{
	recv_data >> this->user_index_ ;	
	LOG_TRACE(("[sucess] connect!! [%d", this->user_index_));

	make_name();

	uint16 send_data_len = sizeof(this->user_index()) + this->user_name_.length();
	
	PacketData send_data(USER_INFO_REGISTER, send_data_len);
	send_data << this->user_index();
	send_data << this->user_name();
	
	return this->send(send_data) ;
}

int DummyHandler::recv_chat_start(PacketData& recvData)
{
	ACE_Time_Value time;
	time.msec(1000);
	int ret = proactor()->schedule_timer(*reinterpret_cast<ACE_Handler*>(this),                            
													   reinterpret_cast<const void*>(static_cast<size_t>(1)), 
													   time, 
													   time);

	return 0;
}

int DummyHandler::recv_chat_message(PacketData& recvData)
{
	int new_user_index = 0;
	std::string new_user_name;
	std::string chat_message;

	recvData >> new_user_index;
	recvData >> chat_message;

	LOG_TRACE(("[%s][%s]", this->user_name(), chat_message.c_str()));
	return 0;
}

///////////////////////////////////////////////////////////////////
// Send
///////////////////////////////////////////////////////////////////
bool DummyHandler::send(PacketData& data)
{
	int result = 0;
	ACE_Message_Block* mb = AllocatorMgr->packet_block_alloc();	
	if(mb)
	{
		mb->copy((char*)&data, sizeof(PK_Header));
		mb->copy((char*)data.contents(), data.size());

		result = writer_.write(*mb, sizeof(PK_Header) + data.size());
	}
	else
	{
		result = -1;
		LOG_ERROR(("ACE_Message_Block Alloc"));

	}
	return result;
}

int DummyHandler::send_random_chat()
{
	int other_user_index = rand() % g_ConnectionCount;
	const char* chat_msg = chat_samples[(rand() % (sizeof(chat_samples) / sizeof(char*)))];

	int send_data_len = sizeof(this->user_index_) + 
										 ACE_OS::strlen(this->user_name()) + 
										 ACE_OS::strlen(chat_msg) +1;

	PacketData send_data(CHAT_MESSAGE, send_data_len);
	send_data << this->user_index();
	send_data << other_user_index;
	send_data << chat_msg;

	if( 0 != this->send(send_data))
	{
		LOG_ERROR(("send fail"));
	}

	return 0;
}